bitkeeper revision 1.825.4.6 (40645529V38YcP4nuYrPCmsUH5J_Bw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 26 Mar 2004 16:07:05 +0000 (16:07 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 26 Mar 2004 16:07:05 +0000 (16:07 +0000)
sched.h, irq.h, physdev.c, irq.c:
  Final piece of guest-PIRQ functionality in Xen.

xen/arch/i386/irq.c
xen/common/physdev.c
xen/include/xen/irq.h
xen/include/xen/sched.h

index 19cf5c7dc486490076dc7ec25cf7e854f002276d..bb252b446db5d4f1b2f0e3818268070aa61bcf62 100644 (file)
@@ -941,7 +941,8 @@ int setup_irq(unsigned int irq, struct irqaction * new)
 
 #define IRQ_MAX_GUESTS 7
 typedef struct {
-    unsigned int nr_guests;
+    unsigned short nr_guests;
+    unsigned short in_flight;
     struct task_struct *guest[IRQ_MAX_GUESTS];
 } irq_guest_action_t;
 
@@ -955,10 +956,39 @@ static void __do_IRQ_guest(int irq)
     for ( i = 0; i < action->nr_guests; i++ )
     {
         p = action->guest[i];
+        if ( !test_and_set_bit(irq, &p->pirq_mask) )
+            action->in_flight++;
         send_guest_pirq(p, irq);
     }
 }
 
+int pirq_guest_unmask(struct task_struct *p)
+{
+    irq_desc_t *desc;
+    int i, j, pirq;
+    u32 m;
+    shared_info_t *s = p->shared_info;
+
+    for ( i = 0; i < 2; i++ )
+    {
+        m = p->pirq_mask[i];
+        while ( (j = ffs(m)) != 0 )
+        {
+            m &= ~(1 << --j);
+            pirq = (i << 5) + j;
+            desc = &irq_desc[pirq];
+            spin_lock_irq(&desc->lock);
+            if ( !test_bit(p->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) &&
+                 test_and_clear_bit(pirq, &p->pirq_mask) &&
+                 (--((irq_guest_action_t *)desc->action)->in_flight == 0) )
+                desc->handler->end(pirq);
+            spin_unlock_irq(&desc->lock);
+        }
+    }
+
+    return 0;
+}
+
 int pirq_guest_bind(struct task_struct *p, int irq)
 {
     unsigned long flags;
@@ -983,7 +1013,8 @@ int pirq_guest_bind(struct task_struct *p, int irq)
             goto out;
 
         action->nr_guests = 0;
-
+        action->in_flight = 0;
+        
         desc->depth = 0;
         desc->status |= IRQ_GUEST;
         desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
@@ -1014,6 +1045,10 @@ int pirq_guest_unbind(struct task_struct *p, int irq)
 
     action = (irq_guest_action_t *)desc->action;
 
+    if ( test_and_clear_bit(irq, &p->pirq_mask) &&
+         (--action->in_flight == 0) )
+        desc->handler->end(irq);
+
     if ( action->nr_guests == 1 )
     {
         desc->action = NULL;
index cc2f21b172883e92e38bf8bd8dac0679d61d6092..11746785f3ee7af28434bba96d597af94f897279 100644 (file)
@@ -564,12 +564,6 @@ static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val)
 }
 
 
-static long pci_unmask_irq(void)
-{
-    return 0;
-}
-
-
 /*
  * demux hypervisor call.
  */
@@ -604,7 +598,7 @@ long do_physdev_op(physdev_op_t *uop)
         break;
 
     case PHYSDEVOP_UNMASK_IRQ:
-        ret = pci_unmask_irq();
+        ret = pirq_guest_unmask(current);
         break;
 
     default:
index 169c4170cb1918b6dcb19c66379db61a856e3483..0e53cc0331ba6565bb7806e4f36ab124524a8f1b 100644 (file)
@@ -58,6 +58,7 @@ extern hw_irq_controller no_irq_type;
 extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
 
 struct task_struct;
+extern int pirq_guest_unmask(struct task_struct *p);
 extern int pirq_guest_bind(struct task_struct *p, int irq);
 extern int pirq_guest_unbind(struct task_struct *p, int irq);
 
index 192c2fcc2206e5cf766549e387dc9c1f79812b1f..c12ac2ca5eaa20830170bfdd33905225aadae98e 100644 (file)
@@ -163,6 +163,7 @@ struct task_struct
      */
     u16 pirq_to_evtchn[64];
     u16 virq_to_evtchn[NR_VIRQS];
+    u32 pirq_mask[2];
 
     /* Physical I/O */
     spinlock_t       pcidev_lock;